package com.fuluwa.domain.order.model;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import org.apache.commons.logging.Log;
import org.apache.commons.scxml.io.SCXMLParser;
import org.apache.commons.scxml.model.ModelException;
import org.apache.commons.scxml.model.SCXML;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import com.fuluwa.infra.state.AbstractStateMachine;


/**
 * @author yongxia
 * @Date Jul 18, 2013 4:58:00 PM
 */
public final class OrderStateMachine extends AbstractStateMachine {
	private static final Logger log = LoggerFactory.getLogger(OrderStateMachine.class);
	private static enum OrderEvent{
		CONFIRM,PAYMENT,CANCEL,COMPLETE
	}
    private static final String XML_CONFIG_FILENAME = "Order.xml";

    /** instance of model */
	private static SCXML config;

	/*
	 * read the state machine configuration, just once though, because it is quite resource intensive.
	 */
    static {
    	final URL configUrl = OrderStateMachine.class.getClassLoader().getResource(XML_CONFIG_FILENAME);
    	try{
    		config = SCXMLParser.parse(configUrl, new ErrorHandler(){
    		    public void error(SAXParseException exception) throws SAXException {
    		        log.error("Couldn't parse SCXML Config (" + configUrl + ")", exception);
    		    }

    		    /**
    		     * @see  ErrorHandler#fatalError(SAXParseException)
    		     */
    		    public void fatalError(SAXParseException exception) throws SAXException {
    		        log.error("Couldn't parse SCXML Config (" + configUrl + ")", exception);
    		    }

    		    /**
    		     * @see  ErrorHandler#warning(SAXParseException)
    		     */
    		    public void warning(SAXParseException exception) throws SAXException {
    		        log.warn("Couldn't parse SCXML Config (" + configUrl + ")", exception);
    		    }
    		});
    	}catch(ModelException e){
    		log.error("Couldn't parse SCXML Config (" + configUrl + ")", e);
    	}catch(SAXException e){
    		log.error("Couldn't parse SCXML Config (" + configUrl + ")", e);
    	}catch(IOException e){
    		log.error("Couldn't parse SCXML Config (" + configUrl + ")", e);
    	}
    }

    /**
     * creates a state machine, with states and transitions based on the given config.
     *
     * @throws  MalformedURLException
     */
    public OrderStateMachine() {
        this(null);
    }

    /**
     * creates a state machine, with states and transitions based on the given config.
     *
     * @param   idOfPersistedState  id of initial state, for cases where we are reading it from persistence.
     *
     * @throws  MalformedURLException
     */
    public OrderStateMachine(String idOfPersistedState) {
        super(config, idOfPersistedState);
    }

    /**
     * trigger the state transition.
     * 
     * @throws  ModelException
     */
    public void triggerConfirm() {
        trigger(OrderEvent.CONFIRM.toString());
    }

    /**
     * trigger the state transition.
     * 
     * @throws  ModelException
     */
    public void triggerPayment() {
        trigger(OrderEvent.PAYMENT.toString());
    }

    /**
     * trigger the state transition.
     * 
     * @throws  ModelException
     */
    public void triggerCancel() {
        trigger(OrderEvent.CANCEL.toString());
    }

    /**
     * trigger the state transition.
     * 
     * @throws  ModelException
     */
    public void triggerComplete() {
        trigger(OrderEvent.COMPLETE.toString());
    }

}
